function [img, count, max_avail] = f5e(img, k, msg, seed)
    % F5E  Embed message using F5.
    % [IMG, COUNT, MAX_AVAIL] = F5E(IMG, K, MSG, START) embed message into
    % IMG, and return the number of bits embeded and the final 
    % image, where K is for F5 and start is used for randomlize.
    % COUNT is the number of bits successfully hidden. 
    % Embeded message is previously bitxor with random binary chars.
    %
    if k <= 0
        error('k must be above zero.');
    end
    n = 2^k - 1;

    % patch msg
    obin = arrayToBinary(msg);
    data_size = size(obin,2);
    if mod(data_size, k) ~= 0
        morebit = k - mod(data_size,k);
    else
        morebit = 0;
    end
    bin = [obin, zeros(1, morebit)];
    
    ROWS = size(img,1)/8;
    r = int16(im2vec(img, [8 8])');
    [M,N] = size(r);

    max_avail = countNonZeroAC(r);
    fprintf(1, 'max_avail = %db\n',max_avail);

    % generate pusedo random sequence, and
    % transform img into random sequence, skip the AC value
    if nargin < 4
        seed = M*N;
    end
    
    rs = getRandStream(seed);
    tran = prand3(M*N, rs);
    
    % hide every bit
    count = 1;    
    usedval = ones(1,n) * -1;
    usedi = usedval;
    usedj = usedval;
    usedlen = 1;
    p = 0;
    
    for i1 = 1:M
        if count > data_size
            break
        end
        for j1 = 1:N
            if count > data_size
                break
            end
            p = p + 1;
            t = tran(1,p);% t=1..N*M
            i = floor((t-1) / N)+1;
            j = (t-1) - (i-1)*N + 1;
            if j == 1
                continue;
            end
            u = r(i, j);
            if u == 0
                continue
            end
            usedi(1, usedlen) = i;
            usedj(1, usedlen) = j;
            usedval(1, usedlen) = u;
            usedlen = usedlen + 1;
            if usedlen > n
                [fb, ndata] = f5_setValue(usedval, mod(bin(1, count:count+k-1) + round(rs.rand(1,k)), 2)  , k, n);
                for z = 1:n
                    r(usedi(z), usedj(z)) = ndata(z);
                end
                if fb >= 0
                    usedval = [usedval(1:fb-1), usedval(fb+1:n), -1];
                    usedi = [usedi(1:fb-1), usedi(fb+1:n), -1];
                    usedj = [usedj(1:fb-1), usedj(fb+1:n), -1];
                    usedlen = usedlen - 1;
                else
                    usedval = ones(1,n) * -1;
                    usedi = usedval;
                    usedj = usedval;
                    usedlen = 1;
                    count = count + k;
                end
            end
        end
    end
    
    count = count - 1;
    img = vec2im(double(r)', [0 0], [8 8], ROWS);
    
    % output

    if count < data_size
        len = floor((count-16)/8);
        fprintf(1, 'part of message hidden in whole image. %3.3f bpp, %3.3f bpc\n', count/M/N, count/max_avail);
        fprintf(1, ' msg = %dB (%db), %3.2f%%\n',len, count,100*count/data_size);
    else
        fprintf(1, 'whole message hidden in part of image. %3.3f bpp, %3.3f bpc\n', count/M/N, count/max_avail);
        fprintf(1, ' coef = %db, %3.2f%%\n',p,100*p/M/N);
    end
end
